#coding:utf-8
import talib
from py_at.strategy import Strategy
from py_at.Data import Data
from py_at.Bar import Bar
import numpy as np
import time
class Thermostat_short(Strategy):
    """
    策略说明:
        通过计算市场的潮汐指数，把市场划分为震荡和趋势两种走势；震荡市中
    采用开盘区间突破进场；趋势市中采用布林通道突破进场。
    系统要素:
        1、潮汐指数
        2、关键价格
        3、布林通道
        4、真实波幅
        5、出场均线
    入场条件:
        1、震荡市中采用开盘区间突破进场
        2、趋势市中采用布林通道突破进场
    出场条件:
        1、震荡市时进场单的出场为反手信号和ATR保护性止损
        2、趋势市时进场单的出场为反手信号和均线出场
    注    意:
        此公式仅做多
    """

    def __init__(self,cfg):
        super().__init__(cfg)
        #初始化参数
        if cfg == "":
            self.Params['swingTrendSwitch']=20
            self.Params['swingPrcnt1']=0.5
            self.Params['swingPrcnt2'] = 0.75
            self.Params['atrLength'] = 10
            self.Params['bollingerLengths'] = 50
            self.Params['numStdDevs'] = 2
            self.Params['trendLiqLength'] = 50
        self.p_lots = self.Params['Lots'] = 1
        self.timeD = ""
        self.cmiVal = []
        self.keyOfDay = []
        self.swingEntry =False
    def OnBarUpdate(self, data=Data, bar=Bar):
        #计算潮汐指数用以区分震荡市与趋势
        if len(self.C)<50:
            return
        if self.timeD!=self.D[-1]:
            self.cmiVal.append(abs(self.C[-2]-self.C[-31])/(max(self.H[-32:])-min(self.L[-32:]))*100)
            self.keyOfDay.append((self.H[-1] + self.L[-1] + self.C[-1]) / 3)
            self.timeD = self.D[-1]
        if(len(self.cmiVal)<2):return

        trendLokBuy = talib.MA(self.L,3)
        trendLokSell = talib.MA(self.H,3)
        #关键价格

        #震荡市中收盘大于关键价格为宜卖市，否则为宜卖市
        buyEasierDay = False;
        sellEasierDay = False;
        if (self.C[-2]> self.keyOfDay[-2]):sellEasierDay =True
        if (self.C[-2]<=self.keyOfDay[-2]):buyEasierDay = True
        #计算震荡市的进场价格
        myATR = talib.ATR(self.H,self.L,self.C,timeperiod=self.Params['atrLength'])
        if(buyEasierDay == True):  #如果是宜买市场
            swingBuyPt = self.O[-1] + self.Params['swingPrcnt1'] * myATR[-2]
            swingSellPt = self.O[-1] - self.Params['swingPrcnt2'] * myATR[-2]
        if(sellEasierDay == True): #如果是宜卖市场
            swingBuyPt = self.O[-1] + self.Params['swingPrcnt2'] * myATR[-2]
            swingSellPt = self.O[-1] - self.Params['swingPrcnt1'] * myATR[-2]
        swingBuyPt = max(swingBuyPt,trendLokBuy[-2])
        swingSellPt = min(swingSellPt,trendLokSell[-2])
        #计算趋势市的进场价格
        upBand, MindLine, dnBand = talib.BBANDS(self.C, timeperiod=self.Params['bollingerLengths'], nbdevup=self.Params['numStdDevs'], nbdevdn=self.Params['numStdDevs'], matype=0)
        trendBuyPt = upBand
        trendSellPt = dnBand
        #震荡市----------------------------------------------------------------------------------------------------------------------------
        if(self.cmiVal[-1]<self.Params['swingTrendSwitch']):
            if (self.PositionShort == 0 and self.L[-1]<=swingSellPt):
                self.SellShort(min(self.O[-1],swingSellPt))
                self.swingEntry = True
                #print("震荡入场 时间{0} 价格{1}".format(self.D[-1], swingSellPt))

            if (self.PositionShort == 1 and self.LastEntryDateShort!=self.D[-1] and self.H[-1] >=swingBuyPt):
                self.BuyToCover(max(self.O[-1],swingBuyPt))
                self.swingEntry = False
                #print("震荡出场 时间{0} 价格{1}".format(self.D[-1], swingBuyPt))
        swingProtStop = 3*myATR
        trendProtStop = talib.MA(self.C,self.Params['trendLiqLength'])

        #趋势市------------------------------------------------------------------------------------------------------------------------------
        if(self.cmiVal[-1]>= self.Params['swingTrendSwitch']):
            if(self.swingEntry==True):
                if(self.PositionShort ==1 and self.LastEntryDateShort!=self.D[-1] and self.H[-1]>=(self.LastEntryPriceShort+swingProtStop[-2])):
                    self.BuyToCover(max(self.O[-1],self.LastEntryPriceShort+swingProtStop[-2]))
                    #print("趋势中震荡出场 时间{0} 价格{1}".format(self.D[-1], self.LastEntryPriceShort+swingProtStop[-2]))
                    self.swingEntry = False
            #趋势市出场
            if(self.swingEntry==False):
                if(self.PositionShort==0 and self.LastEntryDateShort!=self.D[-1] and self.L[-1] <=trendSellPt[-2]):
                    self.SellShort(min(self.O[-1],trendSellPt[-2]))
                    #print("趋势入场 时间{0} 价格{1}".format(self.D[-1], trendSellPt[-2]))
                if(self.PositionShort==1 and self.LastEntryDateShort!=self.D[-1] and self.H[-1]>=min(trendBuyPt[-2],trendProtStop[-2])):
                    self.BuyToCover(max(self.O[-1],min(trendBuyPt[-2],trendProtStop[-2])))
                    #print("趋势出场 时间{0} 价格{1}".format(self.D[-1], min(trendBuyPt[-2],trendProtStop[-2])))






